package com.easylinkin.linkappapi.powerdistribution.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import com.easylinkin.linkappapi.powerdistribution.entity.DistributionElectricPriceConfig;
import com.easylinkin.linkappapi.powerdistribution.entity.DistributionElectricPriceConfigTime;
import com.easylinkin.linkappapi.powerdistribution.mapper.DistributionElectricPriceConfigMapper;
import com.easylinkin.linkappapi.powerdistribution.mapper.DistributionElectricPriceConfigTimeMapper;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.powerdistribution.entity.DistributionElectricPrice;
import com.easylinkin.linkappapi.powerdistribution.mapper.DistributionElectricPriceMapper;
import com.easylinkin.linkappapi.powerdistribution.service.DistributionElectricPriceService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@Slf4j
@Service
public class DistributionElectricPriceServiceImpl extends ServiceImpl<DistributionElectricPriceMapper, DistributionElectricPrice> implements DistributionElectricPriceService {
    @Resource
    LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    DistributionElectricPriceConfigMapper distributionElectricPriceConfigMapper;
    @Resource
    DistributionElectricPriceConfigTimeMapper distributionElectricPriceConfigTimeMapper;

    @Override
    public IPage<DistributionElectricPrice> page(Page page, DistributionElectricPrice distributionElectricPrice) {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        distributionElectricPrice.setTenantId(tenantId);
        return new LambdaQueryChainWrapper<>(baseMapper)
                .eq(DistributionElectricPrice::getTenantId, distributionElectricPrice.getTenantId())
                .like(!StringUtils.isEmpty(distributionElectricPrice.getName()), DistributionElectricPrice::getName, distributionElectricPrice.getName())
                .between(!StringUtils.isEmpty(distributionElectricPrice.getQueryStartTime()) && !StringUtils.isEmpty(distributionElectricPrice.getQueryEndTime()),
                        DistributionElectricPrice::getCreateTime, distributionElectricPrice.getQueryStartTime(), distributionElectricPrice.getQueryEndTime())
                .orderByDesc(DistributionElectricPrice::getCreateTime,DistributionElectricPrice::getModifyTime)
                .page(page);
    }

    @Override
    public List<DistributionElectricPrice> getAll(DistributionElectricPrice distributionElectricPrice) {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        distributionElectricPrice.setTenantId(tenantId);
        return new LambdaQueryChainWrapper<>(baseMapper)
                .eq(DistributionElectricPrice::getTenantId, distributionElectricPrice.getTenantId())
                .like(!StringUtils.isEmpty(distributionElectricPrice.getName()), DistributionElectricPrice::getName, distributionElectricPrice.getName())
                .between(!StringUtils.isEmpty(distributionElectricPrice.getQueryStartTime()) && !StringUtils.isEmpty(distributionElectricPrice.getQueryEndTime()),
                        DistributionElectricPrice::getCreateTime, distributionElectricPrice.getQueryStartTime(), distributionElectricPrice.getQueryEndTime())
                .orderByDesc(DistributionElectricPrice::getCreateTime,DistributionElectricPrice::getModifyTime)
                .list();
    }

    @Override
    public DistributionElectricPrice findAllById(DistributionElectricPrice distributionElectricPrice) {
        Assert.notNull(distributionElectricPrice.getId(), "id 不能为空");
        return baseMapper.findAllById(distributionElectricPrice.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateEntity(DistributionElectricPrice distributionElectricPrice) {
        paramValidate(distributionElectricPrice);
        //参数格式-时间重复效验
        paramRepeatValidate(distributionElectricPrice);
        LocalDateTime now = LocalDateTime.now();
        LinkappUser user = linkappUserContextProducer.getNotNullCurrent();
        distributionElectricPrice.setTenantId(user.getTenantId());
        distributionElectricPrice.setModifier(user.getId() + "");
        distributionElectricPrice.setModifyTime(now);
        //name唯一效验
        paramNameOnlyValidate(distributionElectricPrice);
        boolean falg = false;
        if (StringUtils.isEmpty(distributionElectricPrice.getId())) {
            distributionElectricPrice.setCreator(user.getId() + "");
            distributionElectricPrice.setCreateTime(now);
            save(distributionElectricPrice);
            falg = true;
        } else {
            updateById(distributionElectricPrice);
            falg = false;
        }

        if (StringUtils.isEmpty(distributionElectricPrice.getId())) {
            return;
        }
        if (!falg) {
            //删除子集
            distributionElectricPrice.setIds(Arrays.asList(distributionElectricPrice.getId()));
            removeSubset(distributionElectricPrice);
        }
        //保存子集
        saveSubset(distributionElectricPrice);
    }

    /***
     * 批量删除
     * @param distributionElectricPrice
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeByIds(DistributionElectricPrice distributionElectricPrice) {
        Assert.notEmpty(distributionElectricPrice.getIds(), "ids 不能为空");
        removeByIds(distributionElectricPrice.getIds());
        //删除子集
        removeSubset(distributionElectricPrice);
    }

    /***
     * 保存子集
     * @param distributionElectricPrice
     */
    private void saveSubset(DistributionElectricPrice distributionElectricPrice) {
        if (StringUtils.isEmpty(distributionElectricPrice.getId())) {
            return;
        }
        if (distributionElectricPrice.getDistributionElectricPriceConfigList() == null || distributionElectricPrice.getDistributionElectricPriceConfigList().size() <= 0) {
            return;
        }
        List<DistributionElectricPriceConfig> distributionElectricPriceConfigList = distributionElectricPrice.getDistributionElectricPriceConfigList();
        List<DistributionElectricPriceConfigTime> distributionElectricPriceConfigTimeList = null;
        for (DistributionElectricPriceConfig distributionElectricPriceConfig : distributionElectricPriceConfigList) {
            distributionElectricPriceConfig.setElectricPriceId(distributionElectricPrice.getId());
            distributionElectricPriceConfig.setMonth(JSONObject.toJSONString(distributionElectricPriceConfig.getMonthList()));
            distributionElectricPriceConfigMapper.insert(distributionElectricPriceConfig);
            distributionElectricPriceConfigTimeList = distributionElectricPriceConfig.getDistributionElectricPriceConfigTimeList();
            if (distributionElectricPriceConfigTimeList == null || distributionElectricPriceConfigTimeList.size() <= 0) {
                continue;
            }
            //添加子集
            distributionElectricPriceConfigTimeList = distributionElectricPriceConfigTimeList.stream().map(m -> {
                m.setElectricPriceConfigId(distributionElectricPriceConfig.getId());
                return m;
            }).collect(Collectors.toList());
            distributionElectricPriceConfigTimeMapper.insertList(distributionElectricPriceConfigTimeList);
        }
    }

    /***
     * 删除子集
     * @param distributionElectricPrice
     */
    private void removeSubset(DistributionElectricPrice distributionElectricPrice) {
        if (distributionElectricPrice.getIds() == null || distributionElectricPrice.getIds().size() <= 0) {
            return;
        }
        List<DistributionElectricPriceConfig> distributionElectricPriceConfigList = new LambdaQueryChainWrapper<>(distributionElectricPriceConfigMapper)
                .select(DistributionElectricPriceConfig::getId)
                .in(DistributionElectricPriceConfig::getElectricPriceId, distributionElectricPrice.getIds())
                .list();
        if (distributionElectricPriceConfigList == null || distributionElectricPriceConfigList.size() <= 0) {
            return;
        }
        List<Long> ids = distributionElectricPriceConfigList.stream().map(DistributionElectricPriceConfig::getId).collect(Collectors.toList());
        distributionElectricPriceConfigMapper.deleteBatchIds(ids);
        //删除子集
        new LambdaUpdateChainWrapper<>(distributionElectricPriceConfigTimeMapper)
                .in(DistributionElectricPriceConfigTime::getElectricPriceConfigId, ids)
                .remove();
    }

    /***
     *  效验必填参数
     * @param distributionElectricPrice
     */
    private void paramValidate(DistributionElectricPrice distributionElectricPrice) {
        Assert.notNull(distributionElectricPrice.getName(), "name 不能为空");

    }

    /***
     * 唯一性效验
     * @param distributionElectricPrice
     */
    private void paramNameOnlyValidate(DistributionElectricPrice distributionElectricPrice) {
        Integer count = new LambdaQueryChainWrapper<>(baseMapper)
                .eq(DistributionElectricPrice::getTenantId, distributionElectricPrice.getTenantId())
                .eq(DistributionElectricPrice::getName, distributionElectricPrice.getName())
                .ne(!StringUtils.isEmpty(distributionElectricPrice.getId()), DistributionElectricPrice::getId, distributionElectricPrice.getId())
                .count();
        if (count == null || count <= 0) {
            return;
        }
        throw new IllegalArgumentException("名称[" + distributionElectricPrice.getName() + "]已存在");
    }

    /***
     * 参数重复效验
     * @param distributionElectricPrice
     */
    private void paramRepeatValidate(DistributionElectricPrice distributionElectricPrice) {
        if (distributionElectricPrice == null || distributionElectricPrice.getDistributionElectricPriceConfigList() == null ||
                distributionElectricPrice.getDistributionElectricPriceConfigList().size() <= 0) {
            return;
        }
        List<DistributionElectricPriceConfig> distributionElectricPriceConfigList = distributionElectricPrice.getDistributionElectricPriceConfigList();
        List<Integer> list = new ArrayList<>();
        for (DistributionElectricPriceConfig distributionElectricPriceConfig : distributionElectricPriceConfigList) {
            //月份
            if (distributionElectricPriceConfig.getMonthList() != null && distributionElectricPriceConfig.getMonthList().size() > 0) {
                list.addAll(distributionElectricPriceConfig.getMonthList());
            }
            //时间
            if (distributionElectricPriceConfig.getDistributionElectricPriceConfigTimeList() != null && distributionElectricPriceConfig.getDistributionElectricPriceConfigTimeList().size() > 0) {
                //时间重复效验
                timeRepeatValidate(distributionElectricPriceConfig.getDistributionElectricPriceConfigTimeList());
            }
        }
        //月份重复效验
        monthRepeatValidate(list);
    }

    /***
     * 时间重复效验
     * @param distributionElectricPriceConfigTimeList
     */
    private void timeRepeatValidate(List<DistributionElectricPriceConfigTime> distributionElectricPriceConfigTimeList) {
        //如果为空，或者只有一个则，不做比较
        if (distributionElectricPriceConfigTimeList == null || distributionElectricPriceConfigTimeList.size() <= 0) {
            return;
        }
        if (distributionElectricPriceConfigTimeList.size() == 1) {
            timeNumerValidate(distributionElectricPriceConfigTimeList.get(0));
            return;
        }
        //先排序在比较
        distributionElectricPriceConfigTimeList.sort(Comparator.comparing(DistributionElectricPriceConfigTime::getStartTime));
        //查找不符合规范时间
        int k = 0;
        for (int i = 1; i < distributionElectricPriceConfigTimeList.size(); i++) {
            //效验时间格式
            timeNumerValidate(distributionElectricPriceConfigTimeList.get(i));
            if (distributionElectricPriceConfigTimeList.get(i).getStartTime().isAfter(distributionElectricPriceConfigTimeList.get(k).getEndTime())) {
                //没出现指针右移，继续找
                k++;
                continue;
            }
            //出现
            throw new IllegalArgumentException("时间段[" + distributionElectricPriceConfigTimeList.get(k).getStartTime() + "-" + distributionElectricPriceConfigTimeList.get(k).getEndTime()
                    + "," + distributionElectricPriceConfigTimeList.get(i).getStartTime() + "-" + distributionElectricPriceConfigTimeList.get(i).getEndTime() + "]存在重叠");
        }
    }

    /***
     * 时间比较效验
     * @param distributionElectricPriceConfigTime
     */
    private void timeNumerValidate(DistributionElectricPriceConfigTime distributionElectricPriceConfigTime) {
        if (distributionElectricPriceConfigTime.getEndTime().isAfter(distributionElectricPriceConfigTime.getStartTime())) {
            return;
        }
        throw new IllegalArgumentException("开始时间[" + distributionElectricPriceConfigTime.getStartTime() + "]必须小于结束时间[" + distributionElectricPriceConfigTime.getEndTime() + "]");
    }

    /***
     *  月份重复效验
     * @param list
     */
    private void monthRepeatValidate(List<Integer> list) {
        if (list == null || list.size() <= 0) {
            return;
        }
        HashSet<Integer> set = new HashSet<>();
        for (Integer integer : list) {
            if (set.add(integer)) {
                continue;
            }
            throw new IllegalArgumentException("月份[" + integer + "]存在重复");
        }
    }
}
